package com.example.qt.ptplatform.service.impl;

import com.example.qt.ptplatform.entity.PointRecord;
import com.example.qt.ptplatform.entity.Seed;
import com.example.qt.ptplatform.entity.Torrent;
import com.example.qt.ptplatform.mapper.PointRecordMapper;
import com.example.qt.ptplatform.mapper.SeedMapper;
import com.example.qt.ptplatform.mapper.TorrentMapper;
import com.example.qt.ptplatform.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Service
public class SeedServiceImpl {

    @Autowired
    private TorrentMapper torrentMapper;

    @Autowired
    private SeedMapper seedMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PointRecordMapper pointRecordMapper;


    // 直接在函数中写死文件路径
    private static final String UPLOAD_DIR = "testDir/" +
            "";

    private static final BigDecimal BASE_HOURS = BigDecimal.ONE; // 基础积分系数 1小时
    private static final long GB_BYTES = 1024L * 1024 * 1024; // 1GB的字节数
    private static final double FIXED_SIZE_GB = 5.0; // 固定文件大小（单位GB）
    private static final Random RANDOM = new Random();
    // 添加种子的逻辑
    public UploadResult addSeed(MultipartFile file, int userId, String title, String description, String tags, String category) throws IOException {
        // 1. 保存 .torrent 文件到服务器
        String realFileName=saveTorrentFile(file);

        // 2. 生成模拟文件大小（固定值+随机波动）
        double mockSizeGB = generateMockSize();

        // 2. 更新 torrents 表，保存用户传入的属性
        Torrent torrent = saveTorrent(userId, title, description, tags, category, realFileName, mockSizeGB);

        // 3. 更新 seeds 表，创建种子记录
        createSeedRecord(torrent.getTorrentId(), userId);

        //新增，计算并处理积分
        processPoints(torrent, mockSizeGB);

        // 返回包含积分信息的结果
        return new UploadResult(calculatePoints(mockSizeGB));
    }


    private void processPoints(Torrent torrent, double sizeGB) {
        BigDecimal points = calculatePoints(sizeGB);

        // 更新用户总积分（原子操作）
        userMapper.updateUserPoints(torrent.getUserId(), points);

        // 保存积分记录
        PointRecord record = new PointRecord();
        record.setUserId(torrent.getUserId());
        record.setTorrentId(torrent.getTorrentId());
        record.setPoints(points);
        record.setCreateTime(LocalDateTime.now());
        record.setPointType("uploadSeed");
        pointRecordMapper.insert(record);
    }

    /**
     * 生成模拟文件大小（固定基准值 + 随机波动）
     */
    private double generateMockSize() {
        // 基础值5GB + (-1~+1GB随机波动
        return FIXED_SIZE_GB + (RANDOM.nextDouble() * 2 - 1);
    }

    /**
     * 计算积分（sizeGB × 基础系数）
     */
    private BigDecimal calculatePoints(double sizeGB) {
        return BigDecimal.valueOf(sizeGB)
                .multiply(BASE_HOURS)
                .setScale(2, RoundingMode.HALF_UP);
    }


    public static class UploadResult {
        private final BigDecimal earnedPoints;

        public UploadResult(BigDecimal earnedPoints) {
            this.earnedPoints = earnedPoints;
        }

        public BigDecimal getEarnedPoints() {
            return earnedPoints;
        }
    }


    // 保存 .torrent 文件到服务器
    private String saveTorrentFile(MultipartFile file) throws IOException {
        // 获取上传文件的原始文件名
        String originalFileName = file.getOriginalFilename();

        if (originalFileName == null) {
            throw new IOException("文件名为空");
        }

        // 获取文件扩展名
        String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);

        // 确保文件扩展名为 ".torrent"
        if (!fileExtension.equalsIgnoreCase("torrent")) {
            throw new IOException("上传的文件不是有效的 .torrent 文件");
        }

        // 设置保存文件的路径，直接写死保存路径到 testDir 文件夹
        Path path = Paths.get(UPLOAD_DIR, originalFileName);

        // 创建目录（如果不存在）
        Files.createDirectories(path.getParent());

        // 保存文件到指定目录
        Files.copy(file.getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);

        return originalFileName;  // 返回文件保存路径
    }

    // 更新 torrents 表，保存新的 torrent 记录
    private Torrent saveTorrent(int userId, String title, String description, String tags, String category, String realFileName, Double sizeGB) {
        Torrent torrent = new Torrent();
        torrent.setUserId(userId);
        torrent.setTitle(title);
        torrent.setDescription(description);
        torrent.setTags(tags);
        torrent.setCategory(category);
        torrent.setSizeGB(sizeGB);
        torrent.setUploadTime(LocalDateTime.now());  // 设置上传时间为当前时间
        torrent.setRealFilename(realFileName);

        // 使用 MyBatis-Plus 的 insert 方法插入数据
        torrentMapper.insert(torrent);

        return torrent;
    }

    // 在 seeds 表中创建种子记录
    private void createSeedRecord(int torrentId, int userId) {
        Seed seed = new Seed();
        seed.setUserId(userId);
        seed.setTorrentId(torrentId);
        seed.setStartTime(LocalDateTime.now());  // 设置当前时间为 start_time
        seed.setEndTime(null);  // 结束时间待定
        seed.setDuration(0);    // 持续时间待定

        // 使用 MyBatis-Plus 的 insert 方法插入数据
        seedMapper.insert(seed);
    }

    //定时增加用户保种积分
    @Scheduled(cron = "0 0 * * * ?") // 每小时执行一次
    public void distributeSeedingPoints() {
        List<Seed> activeSeeds = seedMapper.getAllActiveSeed();

        for (Seed seed : activeSeeds) {
            int userId = seed.getUserId();
            int torrentId = seed.getTorrentId();

            Double sizeGB = torrentMapper.getTorrentSizeGBById(torrentId);
            if (sizeGB == null) continue;
            // 4. 每天按种子体积 1:1 比例发放积分（1 GB = 1 积分），保留两位小数
            BigDecimal points = BigDecimal.valueOf(sizeGB).setScale(2, RoundingMode.HALF_UP);

            // 更新用户积分
            userMapper.updateUserPoints(userId, points);

            // 记录积分明细
            PointRecord record = new PointRecord();
            record.setUserId(userId);
            record.setTorrentId(torrentId);
            record.setPoints(points);
            record.setCreateTime(LocalDateTime.now());
            record.setPointType("keepSeed");
            pointRecordMapper.insert(record);
        }

        System.out.println("定时积分发放完成，处理种子数：" + activeSeeds.size());
    }

}



